package com.wk.springboot.realm;

import java.util.HashSet;
import java.util.Set;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Hash;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.Sha1Hash;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

/**
 * @Classname MD5Realm
 * @Description 自定义realm
 * @Date 2020/5/18 11:55
 * @Author by weikai
 */
public class HashRealm extends AuthorizingRealm {

  /**
   * 密码加密要用到的Matcher
   */
  private CredentialsMatcher credentialsMatcher;

  @Override
  public CredentialsMatcher getCredentialsMatcher() {
    return credentialsMatcher;
  }

  @Override
  public void setCredentialsMatcher(
      CredentialsMatcher credentialsMatcher) {
    this.credentialsMatcher = credentialsMatcher;
  }

  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
      throws AuthenticationException {

    AuthenticationInfo info;
    //强转 UsernamePasswordToken
    /**
     * UsernamePasswordToken中获取的username和password都是前端传过来的
     */
    UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
    String username = upToken.getUsername();

    // Null username is invalid
    if (username == null) {
      throw new AccountException("Null usernames are not allowed by this realm.");
    }

    //这个password是从数据库中查出来的
    String password = "123456";

    /**
     * 给密码加密
     */
    String passwordHash = toHash(password, username);

    //这个类会比对页面传过来的密码和数据库的密码
    SimpleAuthenticationInfo saInfo = new SimpleAuthenticationInfo(username, passwordHash, getName());
    saInfo.setCredentialsSalt(ByteSource.Util.bytes(username));
    info = saInfo;

    return info;
  }

  private String toHash(String password, String name) {
    Hash hash = new SimpleHash(Sha1Hash.ALGORITHM_NAME, password, ByteSource.Util.bytes(name), 1024);
    return hash.toHex();
  }

  public static void main(String[] args) {
    String name = "shiro";
    String password = "123456";
    Hash hash = new SimpleHash(Sha1Hash.ALGORITHM_NAME, password, ByteSource.Util.bytes(name), 1024);
    System.out.println(hash.toHex());
  }

  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    Object principal = principals.getPrimaryPrincipal();
    Set<String> roles = new HashSet<>();
    if("shiro".equals(principal)){
      roles.add("shiro");
    }
    System.out.println("hash 会走这里吗");
    SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
    simpleAuthorizationInfo.setRoles(roles);
    return simpleAuthorizationInfo;
  }
}
